<?php
/**
 * Nordic Repository
 * 
 * LICENSE
 * 
 * The new BSD license is applied on this source-file. For further
 * information please visit http://license.nordic-dev.de/newbsd.txt
 * or send an email to andre.moelle@gmail.com.
 */

/**
 * This schema-class is used to encode and decode data. To provide
 * displaying also numeric array there is a node-name that indicates
 * that the element is numeric. The node-name is "item".
 * 
 * @category   Nordic
 * @package    Nordic_Schema
 * @copyright  2007 Nordic Development
 * @license    http://license.nordic-dev.de/newbsd.txt (New-BSD license)
 * @author     Andre Moelle <andre.moelle@gmail.com>
 * @version    $Id: Xml.php 3 2007-07-08 09:21:42Z andre.moelle $
 */
class Nordic_Schema_Xml implements Nordic_Schema_Interface
{
	/**
	 * This method parses an array to a xml-string.
	 * 
	 * It uses recursion to display as many subelements. The content
	 * of those nodes is always utf8-encoded. There is also a way to
	 * display numeric elements of the array as an element. The name
	 * of the node representing numeric elements is "item".
	 * 
	 * @access private
	 * @param String $name name of the actual-node
	 * @param Array $array array to decode
	 * @param Integer $dim number of tabulators
	 * @return String
	 */
	private function _parseArray ($name, $array, $dim = 0)
	{
		$xml = str_repeat("\t", $dim) . '<' . $name . '>' . "\n";
		
		foreach((array)$array as $key => $value)
		{
			if(is_numeric($key))
				$key = 'item';
			
			if(!is_array($value))
			{
				$xml .= 
					str_repeat("\t", $dim + 1) . 
					'<' . $key . '>' . 
						utf8_encode($value) .
					'</'.$key.'>' . "\n";
			}
			else
				$xml .= $this->_parseArray($key, $value, $dim + 1);
		}
		
		$xml .= str_repeat("\t", $dim) . '</' . $name . '>' . "\n";
		
		return $xml;
	}
	
	/**
	 * This method parses a simplexml-object to an array.
	 * 
	 * The output is always utf8-decoded. To provide numeric results
	 * the element with the name "item" represent numeric elements.
	 * 
	 * @access private
	 * @param SimpleXMLElement $xml simplexml-object
	 * @return Array
	 */
	private function _parseObject ($xml)
	{
		$xml = (array)$xml;
		
		foreach($xml as $key => $value)
		{
			if($value instanceof SimpleXMLElement)
			{
				if(count((array)$value) > 0)
					$value = (array)$value;
				else
					$value = '';
				
				$xml[$key] = $value;
			}
			
			if($key == 'item')
			{
				foreach((array)$value as $index => $content)
				{
					$content = (
						(is_array($content) || 
						 $content instanceof SimpleXMLElement) ? 
							$this->_parseObject($content) : 
							(string)utf8_decode($content)
					);
					
					if(!is_numeric($index))
					{
						if(!isset($element))
							$element = array();
						
						$element[$index] = $content;
					}
					else
						$xml[] = $content;
				}
				
				unset($xml[$key]);
				
				if(isset($element))
				{
					$xml[] = $element;
					unset($element);
				}
			}
			else if(is_array($value))
				$xml[$key] = $this->_parseObject($value);
			else
				$xml[$key] = (string)$xml[$key];
		}
		
		return $xml;
	}
	
	/**
	 * @see Nordic_Schema_Interface::decode()
	 */
	public function decode ($array)
	{
		return 
			'<?xml version="1.0" encoding="utf-8"?>' . "\n" . 
			$this->_parseArray('root', $array);
	}
	
	/**
	 * @see Nordic_Schema_Interface::encode()
	 */
	public function encode ($string)
	{
		return $this->_parseObject(simplexml_load_string($string));
	}
}
?>